package com.winter.admin.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.winter.admin.entity.SysMenu;
import com.winter.admin.entity.dto.MenuVO;
import com.winter.admin.mapper.MenuMapper;
import com.winter.admin.service.MenuService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author zhangshuaiyin
 * @since 2021-06-21
 */
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, SysMenu> implements MenuService {
    @Override
    public List<MenuVO> getMenuTrees() {
        SysMenu menu = new SysMenu();
        // 1. 查询菜单数据
        List<SysMenu> menus = menu.selectList(null);
        List<MenuVO> menuVOList = toMenuVOList(menus);

        // 2. 找出一级分类，填充 children 数据
        return menuVOList.stream().filter(vo -> vo.getParentId() == 0)
                .peek(vo -> vo.setChildren(getChildless(vo, menuVOList)))
                .sorted(Comparator.comparingInt(MenuVO::getSort))
                .collect(Collectors.toList());
    }

    @Override
    public MenuVO getMenuById(Integer id) {
        SysMenu menu = new SysMenu();
        menu = menu.selectById(id);
        Assert.notNull(menu, "根据id查询菜单路由失败");
        return toMenuVO(menu);
    }

    @Override
    public void addMenu(MenuVO menuVO) {
        SysMenu menu = toMenu(menuVO);
        menu.insert();
    }

    @Override
    public void updateMenu(MenuVO menuVO) {
        SysMenu menu = toMenu(menuVO);
        menu.updateById();
    }

    @Override
    public void deleteMenu(Integer id) {
        SysMenu menu = new SysMenu();
        menu.deleteById(id);
    }

    /**
     * 递归获取子路由
     *
     * @param root       根路由（父路由）
     * @param menuVOList 路由列表
     * @return 子路由列表
     */
    private List<MenuVO> getChildless(MenuVO root, List<MenuVO> menuVOList) {
        return menuVOList.stream()
                .filter(vo -> vo.getParentId().equals(root.getId()))
                // 找到子菜单
                .peek(vo -> vo.setChildren(getChildless(vo, menuVOList)))
                .sorted(Comparator.comparingInt(MenuVO::getSort))
                .collect(Collectors.toList());
    }

    /**
     * 实体类转 VO 对象：封装 Meta 数据
     *
     * @param menuList 路由列表
     * @return VO List
     */
    private List<MenuVO> toMenuVOList(List<SysMenu> menuList) {
        List<MenuVO> list = new ArrayList<>();
        menuList.forEach(m -> {
            list.add(toMenuVO(m));
        });
        return list;
    }

    private MenuVO toMenuVO(SysMenu m) {
        MenuVO vo = new MenuVO();
        BeanUtils.copyProperties(m, vo);
        MenuVO.Meta meta = new MenuVO.Meta();
        BeanUtils.copyProperties(m, meta);
        vo.setMeta(meta);
        return vo;
    }

    private SysMenu toMenu(MenuVO vo) {
        SysMenu menu = new SysMenu();
        BeanUtils.copyProperties(vo, menu);
        MenuVO.Meta meta = vo.getMeta();
        BeanUtils.copyProperties(meta, menu);
        return menu;
    }
}
